/*
 * Copyright 2002-2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
 * A BeanDefinition describes a bean instance, which has property values,
 * constructor argument values, and further information supplied by
 * concrete implementations.
 *
 * <p>This is just a minimal interface: The main intention is to allow a
 * {@link BeanFactoryPostProcessor} to introspect and modify property values
 * and other bean metadata.
 * ==========================================================================  翻译
 * BeanDefinition描述了一个bean实例，
 * 该实例具有属性值、构造函数参数值以及具体实现提供的进一步信息<p>
 * 这只是一个最小的接口：
 * 主要目的是允许｛@link BeanFactory PostProcessor｝内省和修改属性值和其他bean元数据。
 *
 * @author Juergen Hoeller // 胡尔根·霍勒
 * @author Rob Harrop  // 哈罗普
 * @see ConfigurableListableBeanFactory#getBeanDefinition
 * @see org.springframework.beans.factory.support.RootBeanDefinition
 * @see org.springframework.beans.factory.support.ChildBeanDefinition
 * @since 19.03.2004
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
	/**
	 * 返回此bean是否“抽象”，即不打算实例化
	 * 它本身，而不仅仅是作为具体子bean定义的父级。
	 */
	boolean isAbstract();
	/// 设置当前Bean定义的父定义名称。
	void setParentName(@Nullable String parentName);

	/// 返回当前Bean定义的父定义名称，如果没有父定义则返回null。
	@Nullable
	String getParentName();

	/// 设置Bean定义的类名。
	/// 类名可以在Bean工厂后处理过程中被修改。
	void setBeanClassName(@Nullable String beanClassName);
	/// 返回当前Bean定义的类名。注意，这不一定是运行时的实际类名，可能是从父定义继承或工厂方法调用的类。
	@Nullable
	String getBeanClassName();
	/// =======================================================================  作用域
	/**
	 * 常量标志一个bean的作用范围
	 */
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
	/**
	 * 重写此bean的目标作用域，指定新的作用域名称。
	 *
	 * @see #SCOPE_SINGLETON
	 * @see #SCOPE_PROTOTYPE
	 */
	void setScope(@Nullable String scope);
	@Nullable
	String getScope();
	boolean isSingleton();
	boolean isPrototype();

	/// 设置Bean是否应懒加载。如果设置为false，则在启动时由Bean工厂立即实例化。
	void setLazyInit(boolean lazyInit);
	boolean isLazyInit();///返回Bean是否应懒加载。仅适用于单例Bean。
	///
	///  ============================================================= bean依赖
	/// 设置当前bean依赖的其他bean名称，确保这些依赖bean在当前bean初始化之前被初始化。
	void setDependsOn(@Nullable String... dependsOn);

	@Nullable
	String[] getDependsOn();///返回当前bean依赖的其他bean名称。


	///  ============================================================= 注入优先级（按类型）
	/**
	 * 设置Bean是否可以作为其他Bean的自动注入候选对象。
	 * 此标志仅影响基于类型的自动注入，不影响按名称显式引用的情况
	 */
	void setAutowireCandidate(boolean autowireCandidate);
	boolean isAutowireCandidate();

	/**
	 * 设置Bean是否为优先自动装配候选。如果多个候选中只有一个Bean的此值为true，则它将作为优先选择
	 */
	void setPrimary(boolean primary);
	boolean isPrimary();

	/**
	 * 设置Bean是否为备选候选者。如果所有匹配的候选者中只有一个不是备选，则选择该非备选候选者
	 */
	void setFallback(boolean fallback);
	boolean isFallback();

	/// ==============================================================  工厂配置
	/**
	 * 设置工厂Bean的名称。仅在使用实例化工厂方法时需要指定
	 *
	 * @see #setFactoryMethodName
	 * @see #setBeanClassName
	 */
	void setFactoryBeanName(@Nullable String factoryBeanName);

	@Nullable
	String getFactoryBeanName();

	/**
	 * 设置工厂方法的名称。该方法可以是静态方法或指定工厂Bean上的实例方法。
	 *
	 * @see #setFactoryBeanName
	 * @see #setBeanClassName
	 */
	void setFactoryMethodName(@Nullable String factoryMethodName);

	@Nullable
	String getFactoryMethodName();

	/**
	 * 获取构造函数参数值
	 */
	ConstructorArgumentValues getConstructorArgumentValues();
	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	/// 返回一个MutablePropertyValues对象，该对象包含将要应用到新实例的属性值。
	/// 返回的对象可以在Bean工厂后处理过程中被修改
	MutablePropertyValues getPropertyValues();
	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}


	/// ==================================================================  生命周期方法
	/**
	 * 设置初始化器方法的名称.
	 */
	void setInitMethodName(@Nullable String initMethodName);

	@Nullable
	String getInitMethodName();

	/**
	 * 设置销毁方法的名称.
	 */
	void setDestroyMethodName(@Nullable String destroyMethodName);

	@Nullable
	String getDestroyMethodName();


	/// ==================================================================  角色提示方法
	/**
	 * 角色提示（role hint）。帮助框架和工具了解特定BeanDefinition的角色和重要性
	 *
	 * @see #ROLE_APPLICATION
	 * @see #ROLE_SUPPORT
	 * @see #ROLE_INFRASTRUCTURE
	 */
	void setRole(int role);
	int getRole();
	/// 表示应用程序的主要部分，通常是用户自定义的bean。
	int ROLE_APPLICATION = 0;
	/// 表示配置中的辅助部分，重要但不直接影响整体配置，如外部组件定义中的支持bean。
	int ROLE_SUPPORT = 1;
	/// /// 表示完全后台的角色，与最终用户无关，是组件定义内部工作的一部分
	int ROLE_INFRASTRUCTURE = 2;


	/// bean定义人类可读描述.
	void setDescription(@Nullable String description);
	@Nullable
	String getDescription();

	/// 返回此bean定义的可解析类型，基于bean类或其他特定元数据。
	/// 这通常在运行时合并bean定义上完全解决但不一定是在配置时定义实例上
	ResolvableType getResolvableType();

	/// 返回该BeanDefinition所来自的资源描述，主要用于在发生错误时提供上下文信息。
	@Nullable
	String getResourceDescription();

	/// 返回原始的BeanDefinition，如果存在装饰器，则返回被装饰的BeanDefinition。通过遍历链可以找到用户最初定义的BeanDefinition。
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();
}
